package com.fadadianqi.starter;

import org.springframework.context.ApplicationContext;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.logging.Logger;

public class WebServer {

    private static Logger log = Logger.getLogger(WebServer.class.getCanonicalName());

    private static WebServer instance;

    private ApplicationContext context;

    private String version = "0.5.0";

    private String serverName;

    private String serverHomeDir;

    private boolean shuttingDown;

    public static void main(String[] args) {
        WebServer.getInstance();
    }

    /**
     * Returns the singleton instance of WebServer.
     *
     * @return the server instance.
     */
    public static WebServer getInstance() {
        // return instance;
        if (instance == null) {
            synchronized (WebServer.class) {
                instance = new WebServer();
            }
        }
        return instance;
    }

    /**
     * Constructor. Creates a server and starts it.
     */
    public WebServer() {
        if (instance != null) {
            throw new IllegalStateException("A server is already running");
        }
        instance = this;
        start();
    }

    /**
     * Starts the server using Spring configuration.
     */
    public void start() {
        try {
            if (isStandAlone()) {
                Runtime.getRuntime().addShutdownHook(new ShutdownHookThread());
            }

            locateServer();

            AdminConsole adminConsole = new AdminConsole(serverHomeDir);
            adminConsole.startup();
            if (adminConsole.isHttpStarted()) {
                log.info("Admin console listening at http://"
                        + adminConsole.getAdminHost() + ":"
                        + adminConsole.getAdminPort());
            }
            log.info("WebServer started: " + serverName);
            log.info("Androidpn Server v" + version);
            //
        } catch (Exception e) {
            e.printStackTrace();
            shutdownServer();
        }
    }

    /**
     * Stops the server.
     */
    public void stop() {
        shutdownServer();
        Thread shutdownThread = new ShutdownThread();
        shutdownThread.setDaemon(true);
        shutdownThread.start();
    }

    /**
     * Returns a Spring bean that has the given bean name.
     *
     * @param beanName
     * @return a Srping bean
     */
    public Object getBean(String beanName) {
        return context.getBean(beanName);
    }

    /**
     * Returns the server name.
     *
     * @return the server name
     */
    public String getServerName() {
        return serverName;
    }

    /**
     * Returns true if the server is being shutdown.
     *
     * @return true if the server is being down, false otherwise.
     */
    public boolean isShuttingDown() {
        return shuttingDown;
    }

    /**
     * Returns if the server is running in standalone mode.
     *
     * @return true if the server is running in standalone mode, false otherwise.
     */
    public boolean isStandAlone() {
        boolean standalone;
        try {
            standalone = Class.forName("com.fadadianqi.starter.ServerStarter") != null;
        } catch (ClassNotFoundException e) {
            standalone = false;
        }
        return standalone;
    }

    private void locateServer() throws FileNotFoundException {
        String baseDir = System.getProperty("base.dir", "..");
        log.info("base.dir: " + baseDir);
        if (serverHomeDir == null) {
            try {
                File confDir = new File(baseDir, "conf");
                if (confDir.exists()) {
                    serverHomeDir = confDir.getParentFile().getCanonicalPath();
                }
            } catch (FileNotFoundException fe) {
                // Ignore
                fe.printStackTrace();
            } catch (IOException ie) {
                // Ignore
                ie.printStackTrace();
            }
            log.info("serverHomeDir-1: " + serverHomeDir);
        } else {
            log.info("serverHomeDir-2: " + serverHomeDir);
        }
        if (serverHomeDir == null) {
            System.err.println("Could not locate home.");
            throw new FileNotFoundException();
        } else {
            //Config.setProperty("server.home.dir", serverHomeDir);
            log.info("server.home.dir=" + serverHomeDir);
        }
    }

    private void shutdownServer() {
        shuttingDown = true;
        log.info("WebServer stopped");
    }

    private class ShutdownHookThread extends Thread {
        public void run() {
            shutdownServer();
            log.info("Server halted");
            System.err.println("Server halted");
        }
    }

    private class ShutdownThread extends Thread {
        public void run() {
            try {
                Thread.sleep(5000);
                System.exit(0);
            } catch (InterruptedException e) {
                // Ignore
                e.printStackTrace();
            }
        }
    }

    public String getServerHomeDir() {
        return serverHomeDir;
    }
}

